(function (fruit, util) {
    var _util = fruit.graphic.util;
    var link_color = "#1F6EEE";
    var link_highContrast_color = "#ffff00";
    var link_highContrast_width = 2;
    //TODO:add by afei;
    util.extend(_util, {
        setLinkColor:function (inColor) {
            link_color = inColor;
        },
        getLinkColor:function () {
            return link_color;
        }
    });
    fruit.define("fruit.graphic.TopologyLink", {
        events:['SelectLink', 'OverInterface', 'OutInterface', 'OverLink', 'OutLink'],
        properties:{
            showInterface:{
                getter:function () {
                    return this._showInterface;
                },
                setter:function (value) {
                    this._showInterface = value;
                    this.toggleInterface(value);
                }
            },
            labelPath:{
                getter:function () {
                    return this._label;
                },
                setter:function (value) {
                    this._label = value;
                    this.toggleLabel(value);
                }
            },
            linkDirection:{
                value:false
            }
        },
        methods:{
            init:function (inData, inContext) {
                var self = this;
                this.context = inContext;
                this.data = inData;
                //
                var element = this.element = _util.create("g").classed("link", true);
                var text = this.text = element.append("svg:text")
                    .classed("label", true)
                    .style({
                        'visibility':'hidden',
                        'opacity':'0.8'
                    });
                this.line = this.element.append("path");
                this.bg = this.element.append("path")
                    .style({'stroke-width':"6", 'stroke':'transparent'})
                    .on("mouseover", function () {
                        self.fire('OverLink', d3.event, self);
                    })
                    .on("mouseout", function () {
                        self.fire('OutLink', d3.event, self);
                    })
                    .on("click", function () {
                        self.fire('SelectLink', self);
                    });
                // this.redraw();
                this.__drawInterface();
                //this.dotted();
            },
            getAttr:function (key) {
                return this.data.data[key] || this.element.node().getAttribute(key);
            },
            __drawInterface:function () {
                var self = this;
                var context = this.context;
                var data = this.data;
                var interfacePath = context.interfacePath();
                var interfaceNode = this.interfaceNode = [];
                var interfaces = util.getByPath(interfacePath, data.data);
                if (interfaces) {
                    util.each(interfaces, function (value, key) {
                        var dot = this.element.append("svg:circle")
                            .attr("r", "3")
                            .attr("fill", "#1F6EEE")//
                            .attr("key", key)
                            .attr("value", value)
                            .on("mouseover", function () {
                                self.fire("OverInterface");
                            })
                            .on("mouseout", function () {
                                self.fire("OutInterface");
                            });
                        interfaceNode.push(dot);
                    }, this);
                }
            },
            dotted:function () {
                this.line.attr("stroke-dasharray", "9, 5");
            },
            selected:function () {
                var data = this.data;
                this._selected = true;
                if (data._virtual) {
                } else {
                }
            },
            unSelected:function () {
                if (this._selected) {
                    this._selected = false;
                }
            },
            fadeIn:function (force) {
                if (!this._fade || force) {
                    this.element.node().style.opacity = 1;
                    this._fade = false;
                } else {
//                    debugger;
                    this.fadeOut();
                }
            },
            fadeOut:function (force) {
                if (force) {
                    this._fade = true;
                }
                this.element.node().style.opacity = 0.2;
                //this.element.classed("link fadeOut",true);
            },
            highLight:function (inColor, inStrokeWidth, force) {
                var highContrast = this.context.highContrast();
                var color = inColor || (highContrast ? link_highContrast_color : link_color);
                var strokeWidth = inStrokeWidth || highContrast ? link_highContrast_width : 1;
                this.element.style("opacity", 1);
                this.line.style({
                    "stroke-width":strokeWidth,
                    "stroke":color
                });
                if (force) {
                    this._highLighted = {
                        color:color,
                        strokeWidth:strokeWidth
                    };
                }
            },
            recover:function (force) {
                if (!force && this._highLighted) {
//                    debugger;
                    this.highLight(this._highLighted.color, this._highLighted.strokeWidth, true);
                } else {
                    this.highLight();
                    this._highLighted = null
                }
                this.fadeIn(force);
                //this.element.style("opacity", 0.5);
//                this.line.style({
//                    "stroke-width": 1,
//                    "stroke": link_color
//                })
            },
            node:function () {
                return this.element.node();
            },
            position:function () {
                var data = this.data;
                var xScale = this.context.xScale;
                var yScale = this.context.yScale;
                return {
                    x1:xScale.get(data.source.data.x) || 0,
                    x2:xScale.get(data.target.data.x) || 0,
                    y1:yScale.get(data.source.data.y) || 0,
                    y2:yScale.get(data.target.data.y) || 0
                }
            },
            bound:function () {
                return this.line.node().getBBox();
            },
            midpoint:function () {
                var position = this.position();
                return {
                    x:(position.x1 + position.x2) / 2,
                    y:(position.y1 + position.y2) / 2
                }
            },
            getSourceNode:function () {
                var id = this.data.source.data.id;
                return this.context.getNode(id);
            },
            getTargetNode:function () {
                var id = this.data.target.data.id;
                return this.context.getNode(id);
            },
            toggleInterface:function (isShow) {
                var value = isShow || this.showInterface();
                if (this.interfaceNode.length && !this.context.linkDirection()) {
                    var interface0 = this.interfaceNode[0];
                    var interface1 = this.interfaceNode[1];
                    if (value) {
                        var scale = 0.5 + this.context.scale() / 2;
                        var distance = 35 * scale;
                        var position = this.position();
                        var x_len = position.x2 - position.x1;
                        var y_len = position.y2 - position.y1;
                        var line_len = Math.sqrt(x_len * x_len + y_len * y_len);
                        var xx = distance / line_len * x_len;
                        var yy = distance / line_len * y_len;
                        interface0 && interface0
                            .attr("cx", position.x1 + xx)
                            .attr("cy", position.y1 + yy)
                            .style("display", "block");
                        interface1 && interface1
                            .attr("cx", position.x2 - xx)
                            .attr("cy", position.y2 - yy)
                            .style("display", "block");
                    } else {
                        interface0 && interface0.style("display", "none");
                        interface1 && interface1.style("display", "none");
                    }
                }
            },
            toggleLabel:function (path) {
                var data = this.data;
                var linkLabelPath = path || this.labelPath();
                var label = this.label = util.getByPath(linkLabelPath, data.data);
                if (linkLabelPath) {
                    var xScale = this.context.xScale;
                    var yScale = this.context.yScale;
                    var dx = xScale.get(data.target.data.x) + xScale.get(data.source.data.x);
                    var dy = yScale.get(data.target.data.y) + yScale.get(data.source.data.y);
                    this.text.text(label)
                        .attr("x", function () {
                            return dx / 2 - 30;
                        })
                        .attr("y", function () {
                            return dy / 2;
                        })
                        .style({
                            'visibility':'visible'
                        });
                } else {
                    this.text.style({
                        'visibility':'hidden'
                    });
                }
            },
            __drawLine:function () {
                var data = this.data;
                var xScale = this.context.xScale;
                var yScale = this.context.yScale;
                var line = this.line;
                if (!this.linkDirection()) {
                    line.attr("d", function () {
                        return "M" + xScale.get(data.source.data.x) + "," + yScale.get(data.source.data.y) + " " + xScale.get(data.target.data.x) + "," + yScale.get(data.target.data.y);
                    });
                } else {
                    line.attr("d", function () {
                        var dx = xScale.get(data.target.data.x) - xScale.get(data.source.data.x),
                            dy = yScale.get(data.target.data.y) - yScale.get(data.source.data.y),
                            dr = Math.sqrt(dx * dx + dy * dy) + 100;
                        return "M" + xScale.get(data.source.data.x) + "," + yScale.get(data.source.data.y) + "A" + dr + "," + dr + " 0 0,1 " + xScale.get(data.target.data.x) + "," + yScale.get(data.target.data.y);
                    });
                    line.attr("d", function () {
                        var dx = xScale.get(data.target.data.x) - xScale.get(data.source.data.x),
                            dy = yScale.get(data.target.data.y) - yScale.get(data.source.data.y),
                            dr = Math.sqrt(dx * dx + dy * dy) + 100;
                        return "M" + xScale.get(data.source.data.x) + "," + yScale.get(data.source.data.y)
                            + "A " + dr + " " + dr + ", 0, 0, 1, " + xScale.get(data.target.data.x) + "," + yScale.get(data.target.data.y)
                            + "A " + (dr - 5) + " " + (dr - 5) + ", 0, 0, 0, " + xScale.get(data.source.data.x) + "," + yScale.get(data.source.data.y);
                    });
                    line.attr("fill", "#f00")
                }
                this.bg.attr("d", line.attr("d"));
                this.element.attr("edge_id", data.id);
                this.element.attr("source_id", data.source.data.id);
                this.element.attr("target_id", data.target.data.id);
            },
            redraw:function () {
                this.__drawLine();
                this.toggleInterface();
                this.toggleLabel();
            }
            
        }

    })
})
    (fruit, fruit.util);